package cn.hbu.zlfw.common.base.dao.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import cn.hbu.zlfw.common.base.dao.BaseDao;
import cn.hbu.zlfw.common.util.PageModel;
import cn.hbu.zlfw.common.util.Utility;

/**
 * 
 *@ClassName:BaseDaoImpl.java
 *@Description:  公用的dao接口实现
 *@Author:lxt<839376636@qq.com>
 *@Date:2017年10月6日下午6:44:12
 *@Version:1.1.0
 */
@Repository("baseDao")
public class BaseDaoImpl<T, PK extends Serializable> implements BaseDao<T, PK> {
	/**
	 * 日志
	 */
	public final Logger LOG = LoggerFactory.getLogger(BaseDaoImpl.class);

	private Class<T> entityClass = null;
	private static final int ADD = 1;
	private static final int UPDATE = 2;
	private static final int DELETE = 3;
	private static final int ADD_OR_UPDATE = 4;
	protected static final int BATCH_EXECUTE_COUNT = 50;
	

	/**
	 * 注入SessionFactory
	 */
	@Autowired
	private SessionFactory sessionFactory;

	/**
	 * 初始化entityClass
	 */
	public BaseDaoImpl() {
		Type type = this.getClass().getGenericSuperclass();
		if (type instanceof ParameterizedType) {
			this.entityClass = (Class<T>) ((ParameterizedType) type).getActualTypeArguments()[0];
		}
	}
	protected Session getSession() {
		return sessionFactory.getCurrentSession();
	}
	/*
	 * 
	 * Description：  插入实体信息
	 * @see com.hbu.zlfw.common.base.dao.BaseDao#save(java.lang.Object)
	 */
	@Override
	public PK save(T entity) {
		// TODO Auto-generated method stub
		return (PK) getSession().save(entity);
	}
	/*
	 * 
	 * Description：  更新实体信息
	 * @see com.hbu.zlfw.common.base.dao.BaseDao#updatre(java.lang.Object)
	 */
	@Override
	public void update(T entity) {
		// TODO Auto-generated method stub
		getSession().update(entity);;
	}
	
	
	/*
	 * 
	 * Description： 添加或更新对象信息
	 * @see com.hbu.zlfw.common.base.dao.BaseDao#saveOrUpdate(java.lang.Object)
	 */
	@Override
	public T saveOrUpdate(T entity) {
		getSession().saveOrUpdate(entity);
		return entity;
	}
	/*
	 * 
	 * Description：  删除对象
	 * @see com.hbu.zlfw.common.base.dao.BaseDao#delete(java.lang.Object)
	 */
	@Override
	public void delete(T entity) {
		getSession().delete(entity);
	}

	/*
	 * 
	 * Description：  根据id批量删除
	 * @see com.hbu.zlfw.common.base.dao.BaseDao#deleteByIds(java.io.Serializable[])
	 */
	@Override
	public int deleteByIds(PK[] ids) {
		if (ids == null || ids.length == 0) {
			return 0;
		} else {
			return getSession().createQuery("delete from " + entityClass.getSimpleName() + " where id in(:ids)")
					.setParameterList("ids", ids).executeUpdate();
		}
	}
	/*
	 * 
	 * Description： 根据id查询对象信息
	 * @see com.hbu.zlfw.common.base.dao.BaseDao#getById(java.io.Serializable)
	 */
	@Override
	public T getById(PK id) {
	     if(id != null){
	          return (T)getSession().get(entityClass, id);
	     }else{
	         return null;
	     }
     }
	
	
	/*
	 * 
	 * Description： 根据id查询对象集合
	 * @see com.hbu.zlfw.common.base.dao.BaseDao#getByIds(java.io.Serializable[])
	 */
	@Override
	public List<T> getByIds(PK[] ids) {
		if (ids == null || ids.length == 0) {
			return Collections.emptyList();
		} else {
			return getSession().createQuery("from " + entityClass.getSimpleName() + " where id in(:ids)")
					.setParameterList("ids", ids).list();
		}
	}
	/*
	 * 
	 * Description：  查询对象集合
	 * @see com.hbu.zlfw.common.base.dao.BaseDao#findAll()
	 */
	@Override
	public List<T> findAll() {
		return getSession().createQuery("from " + entityClass.getSimpleName()+" where delState=:delState")
				.setParameter("delState", 0).list();
	}

	
	/*
	 * 
	 * Description：  根据键值对参数查询结果集，并返回分页信息
	 * @see com.hbu.zlfw.common.base.dao.BaseDao#findListByParams(java.lang.String, java.lang.String, java.util.Map, com.hbu.zlfw.common.util.PageModel)
	 */
	@Override
	public PageModel<T> findListByParams(String queryHql, String queryCount,Map<String, Object> params,
			PageModel<T> pageModel) {
		if(queryHql.contains("from Patent")) {
			StringBuffer sbf = new StringBuffer(queryHql);
			sbf.append(" order by p.updateTime desc");
			queryHql = sbf.toString();
		}
		if(queryHql==null || "".equals(queryHql))
			return pageModel;
		//计算paUtil的最大结果集
		if(pageModel!=null)
		{
			pageModel.setTotalCount(getCountResult(queryHql,params,queryCount));
			LOG.debug(queryHql+"语句返回结果集数量："+pageModel.getTotalCount());
		}
		Query query = getSession().createQuery(queryHql);
		Utility.queryParameterUtil(query, params);
		query.setFirstResult(pageModel.getFirstResult());
		query.setMaxResults(pageModel.getPageSize());
		List<T> list = query.list();
		pageModel.setList(list);
		return pageModel;
	}

	
	/*
	 * 
	 * Description：  得到记录集的总数。
	 * @see com.hbu.zlfw.common.base.dao.BaseDao#getCountResult(java.lang.String, java.util.Map, java.lang.String)
	 */
	@Override
	public int getCountResult(String queryHql,Map<String, Object> params,String queryCount) {
		if(queryHql==null || "".equals(queryHql))
			return 0;
		String temp =  "";
		if(queryCount!=null && !"".equals(queryCount)){
			temp = queryCount;
		}else{
			if(queryHql.startsWith("select"))
				temp = queryHql.replaceAll("select .+from ", "select count(*) from");
			else if(queryHql.startsWith("from"))
				temp = "select count(*) " + queryHql;
		}
		String queryString = temp;
		Query query = getSession().createQuery(queryString);
		Utility.queryParameterUtil(query, params);
		return ((Number)query.uniqueResult()).intValue();
	}
	/*
	 * 
	 * Description：  批量插入
	 * @see com.hbu.zlfw.common.base.dao.BaseDao#batchSave(java.util.List)
	 */
	@Override
	public void batchSave(List<T> list) {
		this.batchOperation(list, ADD, BATCH_EXECUTE_COUNT);
	}
	/*
	 * 
	 * Description：  批量更新
	 * @see com.hbu.zlfw.common.base.dao.BaseDao#batchUpdate(java.util.List)
	 */
	@Override
	public void batchUpdate(List<T> list) {
		this.batchOperation(list, UPDATE, BATCH_EXECUTE_COUNT);
	}
	/*
	 * 
	 * Description：  批量删除
	 * @see com.hbu.zlfw.common.base.dao.BaseDao#batchDelete(java.util.List)
	 */
	@Override
	public void batchDelete(List<T> list) {
		this.batchOperation(list, DELETE, BATCH_EXECUTE_COUNT);
	}
	/*
	 * 
	 * Description：  批量插入或更新
	 * @see com.hbu.zlfw.common.base.dao.BaseDao#batchsaveOrUpdate(java.util.List)
	 */
	@Override
	public void batchsaveOrUpdate(List<T> list) {
		this.batchOperation(list, ADD_OR_UPDATE, BATCH_EXECUTE_COUNT);
	}
	/**
	 * 
	 * @Title: batchOperation 
	 * @Description: 该方法供内部调用，进行批量操作
	 * @param ts 操作的对象集合
	 * @param operation 操作
	 * @param batchCount 处理单元数量
	 */
	private void batchOperation(List<T> ts,int operation,int batchCount) {
		int pos = 0;
		boolean flag =true;
		for (T temp : ts) {
			switch (operation) {
			case ADD:
				getSession().save(temp);
				break;
			case UPDATE:
				getSession().update(temp);
				break;
			case DELETE:
				getSession().delete(temp);
				break;
			case ADD_OR_UPDATE:
				getSession().saveOrUpdate(temp);
				break;
			}
			pos++;
			//以batchCount为处理单元
			if (pos % batchCount == 0) {
				flag=false;
				// 只是将Hibernate缓存中的数据提交到数据库，保持与数据库数据的同步
				getSession().flush();
				// 清除内部缓存的全部数据，及时释放出占用的内存
				getSession().clear();
			}
		}
		if(flag) {
			getSession().flush();
			getSession().clear();
		}
	}
}

